home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / etc / shm.c < prev    next >
C/C++ Source or Header  |  1992-03-27  |  7KB  |  286 lines

  1. /* 
  2.  * shm.c --
  3.  *
  4.  *    These routines map system V shared memory calls into 4.3 BSD
  5.  *    calls.
  6.  *
  7.  * Copyright 1990 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. /*
  18. From dillon@postgres.Berkeley.EDU Fri Jun 23 17:17:30 1989
  19.     Here is the support file I wrote for the postgres that implements
  20. most of the shared memory calls through mmap().  The line used to compile
  21. the module is:
  22.  
  23.     cc -I/usr/include -I/usr/att/usr/include -c port.c
  24.  
  25.     The module is not 100% transparent but works well enough that most
  26. programs which use the shared memory calls don't know the difference.
  27.  
  28.     From working with both the shared memory calls and the mmap() calls
  29. It is clear that the mmap() calls are not only superior, but integrate well
  30. into the system whereas the shared memory calls are really nothing more than
  31. a huge hack.  For example, on SUNs one must compile in the exact amount of
  32. memory to reserved for shared memory and this memory cannot be used by the
  33. VM.  What a waste!  The sequent's Dynix OS, on the otherhand, and the mmap()
  34. call in general has no such restrictions.
  35.  
  36.     I'm going blind into this.  Hopefully you have access to both the
  37. mmap includes and the AT&T shared memory includes.
  38.  
  39.                 Luck,
  40.  
  41.  
  42.                     -Matt
  43. */
  44.  
  45. #ifndef lint
  46. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/shm.c,v 1.6 92/03/27 12:25:31 shirriff Exp $ SPRITE (Berkeley)";
  47. #endif /* not lint */
  48. #include <stdio.h>
  49. #include <fcntl.h>
  50. #include <sys/types.h>
  51. #include <sys/stat.h>
  52. #include <sys/ipc.h>
  53. #include <sys/shm.h>    /* att-include file    */
  54. #include <sys/mman.h>
  55. #include <assert.h>
  56.  
  57. #ifndef __STDC__
  58. #define void char
  59. #endif
  60.  
  61. #define LEN 64
  62. #define PRIV "/tmp/post.phm.%d"
  63. #define SHARED "/tmp/post.shm.%d.%d"
  64.  
  65. extern int errno;
  66.  
  67. typedef struct {
  68.     void  *base;
  69.     long  size;
  70.     short exists;
  71.     int key;
  72.     char name[LEN];
  73. } SHMIDS;
  74.  
  75. int _shmTrace = 0;
  76.  
  77. /*
  78.  * In sprite there is no limit on the number of file descriptors.
  79.  * Set this to 64 because that is how many ultrix allows.
  80.  */
  81.  
  82. #ifndef _NFILE
  83. #define _NFILE 64
  84. #endif
  85.  
  86. static SHMIDS ShmIds[_NFILE];
  87.  
  88. /*
  89.  *  shmget(key, size, shmflg)
  90.  *
  91.  *  key might be IPC_PRIVATE in which case a 'private' segment is created
  92.  *  shmflg = file permissions
  93.  *  size = size of shared memory segment
  94.  */
  95.  
  96. shmget(key, size, shmflg)
  97. key_t key;
  98. int size, shmflg;
  99. {
  100.     int fd;
  101.     char buf[LEN];
  102.     int fileflags = O_RDWR;
  103.     extern int errno;
  104.     int i;
  105.  
  106.     if (_shmTrace) {
  107.     printf("call: shmget(%d, %d, %d)\n", key, size, shmflg);
  108.     }
  109.     if ((shmflg & IPC_CREAT) || (shmflg & IPC_PRIVATE))
  110.     fileflags |= O_CREAT;
  111.     if (shmflg & IPC_NOWAIT)
  112.     fileflags |= O_NDELAY;
  113.     if (shmflg & IPC_EXCL)
  114.     fileflags |= O_EXCL;
  115.     if (shmflg & IPC_ALLOC) {
  116.     fprintf(stderr, "shmget: IPC_ALLOC flag not implemented\n");
  117.     exit(1);
  118.     }
  119.  
  120.     if (key == IPC_PRIVATE)
  121.     sprintf(buf, PRIV, getpid());
  122.     else
  123.     sprintf(buf, SHARED, gethostid(), key);
  124.     fd = open(buf, fileflags, (shmflg & 0777) | 0600);
  125.     if (fd < 0) {
  126.     return -1;
  127.     }
  128.     if ((fileflags & O_CREAT) || key == IPC_PRIVATE) {
  129.     lseek(fd,(long)size-1,0);
  130.     read(fd,buf,1);
  131.     lseek(fd,(long)size-1,0);
  132.     write(fd,buf,1);
  133.     } else {
  134.     size = lseek(fd,0L,2);
  135.     lseek(fd,0L,0);    /* not really needed, in for conformity */
  136.     if (_shmTrace) {
  137.         printf("Segment already has length %d\n", size);
  138.     }
  139.     }
  140.     if (key == IPC_PRIVATE) {
  141.     unlink(buf);
  142.     } else {
  143.     /*
  144.      * See if we already have an entry in the table.
  145.      */
  146.     for (i=0; i< _NFILE; i++) {
  147.         if (key == ShmIds[i].key && ShmIds[i].exists) {
  148.         close(fd);
  149.         if (_shmTrace) {
  150.             printf("Segment already exists as %d\n", i);
  151.         }
  152.         return i;
  153.         }
  154.     }
  155.     }
  156.     ShmIds[fd].size = size;
  157.     ShmIds[fd].base = (void *)0L;
  158.     ShmIds[fd].exists = 1;
  159.     ShmIds[fd].key = key;
  160.     strncpy(ShmIds[fd].name, buf, LEN);
  161.     if (_shmTrace) {
  162.     printf("shmget returning %d\n", fd);
  163.     }
  164.     return(fd);
  165. }
  166.  
  167. shmop()
  168. {
  169.     assert(0);
  170. }
  171.  
  172. shmctl(shmid, cmd, buf)
  173. int shmid, cmd;
  174. struct shmid_ds *buf;    /* sys/shm.h att-includes */
  175. {
  176.     struct stat stat;
  177.     int result = 0;
  178.  
  179.     if (_shmTrace) {
  180.     printf("call: shmctl(%d, %d, %d)\n", shmid, cmd, buf);
  181.     }
  182.     assert(shmid >= 0 && shmid < _NFILE);
  183.     assert(ShmIds[shmid].exists);
  184.  
  185.     fstat(shmid, &stat);
  186.  
  187.     switch(cmd) {
  188.     case IPC_STAT:
  189.     buf->shm_perm.mode= stat.st_mode;
  190.     buf->shm_perm.uid = stat.st_uid;
  191.     buf->shm_perm.gid= stat.st_gid;
  192.     buf->shm_perm.cuid = stat.st_uid;
  193.     buf->shm_perm.cgid= stat.st_gid;
  194.     buf->shm_perm.key = shmid;
  195.     buf->shm_atime = stat.st_atime;
  196.     buf->shm_ctime = stat.st_ctime;
  197.     /* fill in more??? */
  198.     break;
  199.     case IPC_SET:    /* set only uid, guid, and low 9 bits of mode   */
  200.     fchmod(shmid, (stat.st_mode & ~0777) | (buf->shm_perm.mode & 0777));
  201.     fchown(shmid, buf->shm_perm.uid, buf->shm_perm.gid);
  202.     break;
  203.     case IPC_RMID:   /* delete the shared memory identifier        */
  204.     if (ShmIds[shmid].key != IPC_PRIVATE) {
  205.         unlink(ShmIds[shmid].name);
  206.     }
  207.     close(shmid);
  208.     ShmIds[shmid].exists = 0;
  209.     ShmIds[shmid].key = -1;
  210.     break;
  211.     }
  212.     return(result);
  213. }
  214.  
  215. char *
  216. shmat(shmid, shmaddr, shmflg)
  217. int shmid;
  218. int shmaddr;
  219. int shmflg;
  220. {
  221.     void *base;
  222.     long size;
  223.     long pgmask = getpagesize() - 1;
  224.  
  225.     if (_shmTrace) {
  226.     printf("call: shmat(%d, %d, %d)\n", shmid, shmaddr, shmflg);
  227.     }
  228.     assert(!shmaddr);
  229.     assert(!shmflg);
  230.  
  231.     assert(shmid >= 0 && shmid < _NFILE);
  232.     assert(ShmIds[shmid].exists);
  233.  
  234.     if (ShmIds[shmid].base)        /* already mapped! */
  235.     return((char *)ShmIds[shmid].base);
  236.     base = (void *)(((int)sbrk(0) + pgmask) & ~pgmask);
  237.     size = (ShmIds[shmid].size + pgmask) & ~pgmask;
  238.     if (_shmTrace) {
  239.     printf("Mapping: length = %d\n", size);
  240.     }
  241.     if (_shmTrace) {
  242.     printf("shmat: calling mmap(%x, %d, %d, %d, %d, %d)\n", base, size,
  243.         PROT_READ|PROT_WRITE, MAP_SHARED, shmid, 0);
  244.     }
  245.     base = (void *)mmap(base, size, PROT_READ|PROT_WRITE, MAP_SHARED,
  246.         shmid, 0);
  247.     if (base < 0) {
  248.     if (_shmTrace) {
  249.         printf("mmap failed: base = %d, errno = %d\n", base, errno);
  250.     }
  251.     return((char *)-1);
  252.     }
  253.     ShmIds[shmid].base = base;
  254.     if (_shmTrace) {
  255.     printf("shmat returning 0x%x\n", base);
  256.     }
  257.     return((char *)base);
  258. }
  259.  
  260. int
  261. shmdt(shmaddr)
  262. void *shmaddr;
  263. {
  264.     short i;
  265.  
  266.     if (_shmTrace) {
  267.     printf("call: shmdt(%d)\n", shmaddr);
  268.     }
  269.     assert(shmaddr);
  270.  
  271.     for (i = 0; i < _NFILE; ++i) {
  272.     if (ShmIds[i].exists && ShmIds[i].base == shmaddr) {
  273.         if (munmap(ShmIds[i].base, ShmIds[i].size) < 0) {
  274.         fprintf(stderr, "munmap failed!\n");
  275.         exit(1);
  276.         }
  277.         ShmIds[i].base = 0;
  278.         break;
  279.     }
  280.     }
  281.     return(0);
  282. }
  283.  
  284.  
  285.  
  286.